home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / fractal / retinmnd.lha / main.c < prev    next >
C/C++ Source or Header  |  1993-07-18  |  8KB  |  330 lines

  1. /* main.c
  2.    This is a quickie program to generate a mandelbrot set on a Retina
  3.    screen in 256 colors. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <math.h>
  8.  
  9. #ifdef _M68881
  10. #include <m68881.h>
  11. #endif
  12.  
  13. #include <exec/libraries.h>
  14.  
  15. #include <clib/exec_protos.h>
  16. #include <clib/intuition_protos.h>
  17. #include <devices/timer.h>
  18. #include <clib/alib_protos.h>
  19. #include <time.h>
  20.  
  21. #include <pragmas/exec_pragmas.h>
  22. #include <pragmas/intuition_pragmas.h>
  23.  
  24. #include "retina.h"
  25. #include "retina_protos.h"
  26. #include "retina_pragmas.h"
  27.  
  28. #define MAX_ORBITS 256
  29.  
  30. /* uncomment the following line to use my_RectFill */
  31.  
  32. #define MYRECTFILL 1
  33.  
  34. /* uncomment the following line to avoid repeating calculations */
  35. /* WARNING: For some reason this creates code that will cause
  36.    stack overflow errors on any image larger than 320x400 or so */
  37. /*
  38. #define NOREPEATCALC
  39. */
  40.  
  41. struct BrotPoint {
  42.   unsigned int x, y;
  43.   double r, i;
  44. #ifndef NOREPEATCALC
  45.   int orbits; /* -2 if untested, -1 if never escapes,
  46.          >= 0 otherwise */
  47. #endif
  48. };
  49.  
  50. static int max_orbits = MAX_ORBITS;
  51.  
  52. void Compute_Block(struct BrotPoint, struct BrotPoint);
  53. short int __inline __regargs Test_Point(double, double);
  54. #ifdef MYRECTFILL
  55. void __inline __regargs my_RectFill(unsigned int, unsigned int,
  56.                     unsigned int, unsigned int);
  57. #endif
  58.  
  59. /* stack space must be BIG */
  60. long __stack = 100000;
  61.  
  62. /* version string */
  63. UBYTE vers[] = "$VER: RetinaMand V0.1 (18.7.93)";
  64.  
  65. extern struct IntuitionBase *IntuitionBase;
  66. struct _xy_RetinaBase *RetinaBase;
  67. struct DefaultScreenInfo screen_info;
  68.  
  69. int __oslibversion = 37;
  70.  
  71. double dr, di;
  72. struct RetinaScreen *rScreen;
  73.  
  74. int main(int argc, char *argv[])
  75. {
  76.   register int i, rstep, gstep, bstep;
  77.   register UBYTE foo, bar, baz;
  78.   struct BrotPoint start, end;
  79.  
  80.   if ((RetinaBase = (struct _xy_RetinaBase *)
  81.        OpenLibrary("retina.library", 2L)) != NULL) {
  82.     if ((IntuitionBase = (struct IntuitionBase *)
  83.      OpenLibrary("intuition.library", 37L)) != NULL) {
  84.       if ((rScreen = Retina_OpenScreen(RSCR_STDWIDTH, RSCR_STDHEIGHT,
  85.                        MID_DEFAULT_08,
  86.                        RSFF_AUTOADJUST, 0L))
  87.       != NULL) {
  88.     printf("Screen Opened successfully: %d by %d\n",
  89.            rScreen->_rs_Width, rScreen->_rs_Height);
  90.  
  91.     /* set up screen colors; color 0 must always be black */
  92.     Retina_SetPalette(rScreen, 0, 0, 0, 0);
  93.     srand48((long) time(NULL));
  94.     foo = (lrand48() >> 3) % 256;
  95.     bar = (lrand48() >> 4) % 256;
  96.     baz = (lrand48() >> 3) % 256;
  97.     rstep = bstep = (lrand48() >> 5) % 16;
  98.     gstep = (lrand48() >> 5) % 10;
  99.     for (i = 1; i < 256; i++) {
  100.       Retina_SetPalette(rScreen, i, foo, bar, baz);
  101.       foo += rstep;  foo %= 256;
  102.       bar += gstep;  bar %= 256;
  103.       baz += bstep;  baz %= 256;
  104.     }
  105.     Retina_SetDrMd(rScreen, RDM_JAM1);
  106.  
  107.     dr = (2.0 - (-2.0))/((double) rScreen->_rs_Width);
  108.     di = (-1.5 - 1.5)/((double) rScreen->_rs_Height);
  109.  
  110.     /* OK, folks, enough initializing.  Let's call the
  111.        Mbrot routine. */
  112.     start.x = 0; start.r = -2.0; start.y = 0; start.i = 1.5;
  113.     end.x = rScreen->_rs_Width >> 1; end.r = 0.0;
  114.     end.y = rScreen->_rs_Height >> 1; end.i = 0.0;
  115. #ifndef NOREPEATCALC
  116.     start.orbits = -2;
  117.     end.orbits = -2;
  118. #endif
  119.     Compute_Block(start, end);
  120.     start.y = end.y + 1; start.i = end.i + di;
  121.     end.y = rScreen->_rs_Height - 1; end.i = -1.5;
  122.     Compute_Block(start, end);
  123.     start.x = end.x + 1; start.r = end.r + dr;
  124.     end.x = rScreen->_rs_Width - 1; end.r = 2.0;
  125.     Compute_Block(start, end);
  126.     start.y = 0; start.i = 1.5;
  127.     end.y = rScreen->_rs_Height >> 1; end.i = 0.0;
  128.     Compute_Block(start, end);
  129.  
  130.     printf("Hit any key to quit.\n");
  131.     getch();
  132.  
  133.     Retina_CloseScreen(rScreen);
  134.       }
  135.       else {
  136.     fprintf(stderr, "Unable to open Retina screen.\n");
  137.       }
  138.     }
  139.     else {
  140.       fprintf(stderr, "Can't open intuition.library V37+\n");
  141.     }
  142.   }
  143.   else {
  144.     fprintf(stderr, "Can not open retina.library!\n");
  145.   }
  146. }
  147.  
  148. void Compute_Block(struct BrotPoint uleft, struct BrotPoint lright)
  149. {
  150.   unsigned int i;
  151.   double j;
  152.   short int q, z;
  153.  
  154.   if (lright.x - uleft.x < 2 && lright.y - uleft.y < 2) {
  155. #ifdef NOREPEATCALC
  156.     q = Test_Point(uleft.r, uleft.i);
  157.     if (q > 0) Retina_SetPixel(rScreen, uleft.x, uleft.y, q);
  158. #else
  159.     if (uleft.orbits == -2)
  160.       uleft.orbits = Test_Point(uleft.r, uleft.i);
  161.     if (uleft.orbits > 0) Retina_SetPixel(rScreen, uleft.x, uleft.y,
  162.                       uleft.orbits);
  163. #endif
  164.     q = Test_Point(uleft.r, lright.i);
  165.     if (q > 0) Retina_SetPixel(rScreen, uleft.x, lright.y, q);
  166. #ifdef NOREPEATCALC
  167.     q = Test_Point(lright.r, lright.i);
  168.     if (q > 0) Retina_SetPixel(rScreen, lright.x, lright.y, q);
  169. #else
  170.     if (lright.orbits == -2)
  171.       lright.orbits = Test_Point(lright.r, lright.i);
  172.     if (lright.orbits > 0) Retina_SetPixel(rScreen,
  173.                        lright.x, lright.y,
  174.                        lright.orbits);
  175. #endif
  176.     q = Test_Point(lright.r, uleft.i);
  177.     if (q > 0) Retina_SetPixel(rScreen, lright.x, uleft.y, q);
  178.     return;
  179.   }
  180.  
  181.   /* draw a box -- if the borders are all the same, then fill it that
  182.      color */
  183.   q = Test_Point(uleft.r, uleft.i);  uleft.orbits = q;
  184.   if (q > 0)
  185.     Retina_SetPixel(rScreen, uleft.x, uleft.y, q);
  186.   z = Test_Point(lright.r, lright.i);  lright.orbits = z;
  187.   if (z > 0)
  188.     Retina_SetPixel(rScreen, lright.x, lright.y, z);
  189.   if (z != q) {
  190.     goto recurse;
  191.   }
  192.  
  193.   /* top & bottom */
  194.   for (i = uleft.x, j = uleft.r; i <= lright.x; i++, j += dr) {
  195.     z = Test_Point(j, uleft.i);
  196.     if (z != q) {
  197.       goto recurse;
  198.     }
  199.     else {
  200.       if (z > 0)
  201.     Retina_SetPixel(rScreen, i, uleft.y, z);
  202.     }
  203.     z = Test_Point(j, lright.i);
  204.     if (z != q) {
  205.       goto recurse;
  206.     }
  207.     else {
  208.       if (z > 0)
  209.     Retina_SetPixel(rScreen, i, lright.y, z);
  210.     }
  211.   }
  212.   /* left and right */
  213.   for (i = uleft.y, j = uleft.i; i <= lright.y; i++, j += di) {
  214.     z = Test_Point(uleft.r, j);
  215.     if (z != q) {
  216.       goto recurse;
  217.     }
  218.     else {
  219.       if (z > 0)
  220.     Retina_SetPixel(rScreen, uleft.x, i, z);
  221.     }
  222.     z = Test_Point(lright.r, j);
  223.     if (z != q) {
  224.       goto recurse;
  225.     }
  226.     else {
  227.       if (z > 0)
  228.     Retina_SetPixel(rScreen, lright.x, i, z);
  229.     }
  230.   }
  231.  
  232.   /* if we passed through all that, we draw a filled rectangle */
  233.   if (q > 0) {
  234.     Retina_SetAPen(rScreen, q);
  235.  
  236. #ifdef MYRECTFILL
  237.     my_RectFill(uleft.x, uleft.y, lright.x, lright.y);
  238. #else
  239.     /* fakin' it with line drawing */
  240.     for (i = uleft.y; i <= lright.y; i++)
  241.       Retina_Line(rScreen, uleft.x, i, lright.x, i);
  242. #endif
  243.   }
  244.   return;
  245.  
  246.  recurse:
  247.   {
  248.     struct BrotPoint top, bot, left, right, middle;
  249.  
  250.     top.x = bot.x = middle.x = (uleft.x + lright.x) >> 1;
  251.     left.y = right.y = middle.y = (uleft.y + lright.y) >> 1;
  252.     top.r = bot.r = middle.r = (uleft.r + lright.r)/2.0;
  253.     left.i = right.i = middle.i = (uleft.i + lright.i)/2.0;
  254.     top.y = uleft.y; top.i = uleft.i;
  255.     bot.y = lright.y; bot.i = lright.i;
  256.     left.x = uleft.x; left.r = uleft.r;
  257.     right.x = lright.x; right.r = lright.r;
  258. #ifndef NOREPEATCALC
  259.     middle.orbits = top.orbits = bot.orbits = left.orbits =
  260.       right.orbits = -2;
  261. #endif
  262.  
  263.     Compute_Block(uleft, middle);
  264. #ifdef NOREPEATCALC
  265.     left.y += 1; left.i += di;
  266. #endif
  267.     Compute_Block(left, bot);
  268. #ifdef NOREPEATCALC
  269.     middle.x += 1; middle.y += 1;
  270.     middle.r += dr; middle.i += di;
  271.     top.x += 1; top.r += dr;
  272. #endif
  273.     Compute_Block(middle, lright);
  274.     Compute_Block(top, right);
  275.   }
  276. }
  277.  
  278. #ifdef MYRECTFILL
  279. void __inline __regargs my_RectFill(unsigned int x1, unsigned int y1,
  280.                     unsigned int x2, unsigned int y2)
  281. {
  282.   short int tx1, tx2, v;
  283.  
  284.   /* a little magic because Retina_RectFill() ignores the low-order
  285.      3 bits of the x-coords for 256-color screens */
  286.   tx1 = (x1 >> 3) + 1; tx2 = (x2 >> 3) - 1;
  287.   tx1 <<= 3;  tx2 <<= 3;
  288.  
  289.   if (tx2 > tx1) {
  290.     Retina_RectFill(rScreen, tx1, y1, tx2, y2);
  291.     if (x2 - tx2 > 1) {
  292.       for (v = tx2; v <= x2; v++)
  293.     Retina_Line(rScreen, v, y1, v, y2);
  294.     }
  295.     if (tx1 - x1 > 1) {
  296.       for (v = x1; v <= tx1; v++)
  297.     Retina_Line(rScreen, v, y1, v, y2);
  298.     }
  299.   }
  300.   else {
  301.     /* fake it with line drawing */
  302.     for (v = y1; v <= y2; v++) {
  303.       Retina_Line(rScreen, x1, v, x2, v);
  304.     }
  305.   }
  306. }
  307. #endif
  308.  
  309. /* Test_Point() tests points in the C plane to determine
  310.    whether they orbit stably or escape to infinity.
  311.    Returns the escape velocity or -1 if the point is
  312.    in the M-set. */
  313.  
  314. short int __inline __regargs Test_Point(double cx, double cy)
  315. {
  316.   double x = 0.0, y = 0.0, tx;
  317.   register short int i;
  318.  
  319.   /* z = z^2 + c */
  320.   for (i = 0; i < max_orbits; i++) {
  321.     tx = x*x - y*y + cx;
  322.     y = 2.0 * x * y + cy;
  323.     x = tx;
  324.     if (x*x + y*y > 4.0) {
  325.       return(i);
  326.     }
  327.   }
  328.   return(-1);
  329. }
  330.